package com.zingrow.web.report.utils;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;

import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.apache.commons.lang3.StringUtils;

import com.zingrow.common.exception.NumberErrorException;
import com.zingrow.web.report.base.Cycle;
import com.zingrow.web.report.response.PlanItem;

/**
 * 报告模块工具类
 * 
 * @author sywd
 *
 */
public final class ReportUtils {
    /**
     * 排行的值,暂时取前十为0-9数字
     */
    public static final int[] RANK_NUMS = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    /**
     * 日期格式化
     */
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
    /**
     * 数字补位格式化
     */
    private static NumberFormat numberFormat = NumberFormat.getInstance();
    static {
        // 设置是否使用分组
        numberFormat.setGroupingUsed(false);
        // 设置最大整数位数
        numberFormat.setMaximumIntegerDigits(2);
        // 设置最小整数位数
        numberFormat.setMinimumIntegerDigits(2);
    }

    private ReportUtils() {
    }

    /**
     * 拼接维度id---默认周期类型为每日统计
     */
    public static synchronized long buildId(Date date, int planNum, int rankNum) throws NumberErrorException {
        return buildId(date, planNum, rankNum, Cycle.DAY.getCode());
    }

    /**
     * 拼接维度表id（方案id-日期(八位：20170707)-周期类型(两位：01)-排行(暂为两位：01)）
     * 
     * @param date
     *            日期
     * @param planNum
     *            方案id数值
     * @param rankNum
     *            排行/渠道序号
     * @param cycleNum
     *            周期类型id,这里的周期id不一定是日报/周报/月报等报告类型.仅表示数据统计是按日、周、月来统计。
     * @return 拼接后的long类型id
     */
    public static synchronized long buildId(Date date, int planNum, int rankNum, int cycleNum)
            throws NumberErrorException {
        if (rankNum < 0 || rankNum >= 100 || cycleNum <= 0 || cycleNum >= 100 || planNum <= 0 || planNum >= 9000000) {
            throw new NumberErrorException("所设数值已超过系统预期范围");
        }
        StringBuilder sb = new StringBuilder();
        sb.append(planNum).append(dateFormat.format(date)).append(numberFormat.format(cycleNum))
                .append(numberFormat.format(rankNum));
        return Long.parseLong(sb.toString());
    }

    /**
     * 直接组装多个维度id---默认周期类型为每日统计
     */
    public static synchronized List<Long> buildIdsDay(List<Date> dates, List<Integer> planIds, int... rankNums) {
        return buildIds(dates, planIds, Cycle.DAY.getCode(), rankNums);
    }

    /**
     * 直接组装多个维度id
     */
    public static synchronized List<Long> buildIds(List<Date> dates, List<Integer> planIds, int cycleNum,
            int... rankNums) {
        List<Long> list = new ArrayList<>();
        for (Date date : dates) {
            for (int planId : planIds) {
                for (int num : rankNums) {
                    try {
                        list.add(buildId(date, planId, num, cycleNum));
                    } catch (NumberErrorException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        if (list.size() < 1) {
            list.add(-1L);
        }
        return list;
    }

    /**
     * 直接组装多个维度id（）方案对象）---默认周期类型为每日统计
     */
    public static synchronized List<Long> buildIdsODay(List<Date> dates, List<PlanItem> plans, int... rankNums) {
        return buildIdsO(dates, plans, Cycle.DAY.getCode(), rankNums);
    }

    /**
     * 直接组装多个维度id（）方案对象）
     */
    public static synchronized List<Long> buildIdsO(List<Date> dates, List<PlanItem> plans, int cycleNum,
            int... rankNums) {
        List<Long> list = new ArrayList<>();
        for (int num : rankNums) {
            for (Date date : dates) {
                for (PlanItem planItem : plans) {
                    try {
                        list.add(buildId(date, planItem.getPlanId(), num, cycleNum));
                    } catch (NumberErrorException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        if (list.size() < 1) {
            list.add(-1L);
        }
        return list;
    }

    /**
     * 获取自定义零点的时间戳 为匹配mongoDB库数据 时间戳不需要/1000
     * 
     * @param date
     * @return
     */
    public static Long getStart(Date date, int num) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstdate = null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -num); // 得到前一天
        date = calendar.getTime();
        String str = format.format(date);
        try {
            firstdate = format1.parse(str);
        } catch (ParseException e) {
            System.out.println("时间格式转换异常");
        }
        return firstdate.getTime();
    }

    /**
     * 获取当天的零点的时间戳 为匹配mongoDB库数据 时间戳不需要/1000
     * 
     * @param date
     * @return
     */
    public static Long getEnd(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date firstdate = null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        date = calendar.getTime();
        String str = format.format(date);
        try {
            firstdate = format1.parse(str);
        } catch (ParseException e) {
            System.out.println("时间格式转换异常");
        }
        return firstdate.getTime();
    }

    /**
     * List深复制
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deepCopyList(List<T> src) {
        List<T> dest = null;
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            dest = (List<T>) in.readObject();
        } catch (IOException e) {

        } catch (ClassNotFoundException e) {

        }
        return dest;
    }

    /**
     * 正则替换字符串中的元素
     */
    public static String getReplaceAll(String input, String regex, String replacement) {
        if (input == null)
            return null;
        return Pattern.compile(regex).matcher(input).replaceAll(replacement);
    }

    /**
     * 获取图像流的维度信息
     */
    public static Dimension getImgDimension(InputStream inputStream) {
        if (inputStream == null) {
            return null;
        }
        BufferedImage image = null;
        try {
            image = ImageIO.read(inputStream);
            if (image == null) {
                return null;
            }
            return restrictMaxSize(new Dimension(image.getWidth(), image.getHeight()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.reset();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 限制图片的最大大小
     */
    private static Dimension restrictMaxSize(Dimension size) {
        int width = size.width;
        int height = size.height;
        if (width > 425) {
            height = height * 425 / width;
            width = 425;
            size.height = height;
            size.width = width;
        }
        return size;
    }

    /**
     * 将svgcode字符串转为png,并以输入流InputStream的形式返回，以便写入文档
     */
    public static InputStream convertToPng(String svgCode) {
        return new ByteArrayInputStream(convertToPngByte(svgCode));
    }

    public static byte[] convertToPngByte(String svgCode) {
        if (StringUtils.isBlank(svgCode)) {
            return null;
        }
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            byte[] bytes = svgCode.getBytes("UTF-8");
            PNGTranscoder t = new PNGTranscoder();
            TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes));
            TranscoderOutput output = new TranscoderOutput(outputStream);
            t.transcode(input, output);
            outputStream.flush();
            return outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static void convertToPng(String svgCode, String pngFilePath) throws IOException, TranscoderException {

        File file = new File(pngFilePath);

        FileOutputStream outputStream = null;
        try {
            file.createNewFile();
            outputStream = new FileOutputStream(file);
            convertToPng(svgCode, outputStream);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void convertToPng(String svgCode, OutputStream outputStream) throws TranscoderException, IOException {
        try {
            byte[] bytes = svgCode.getBytes("UTF-8");
            PNGTranscoder t = new PNGTranscoder();
            TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes));
            TranscoderOutput output = new TranscoderOutput(outputStream);
            t.transcode(input, output);
            outputStream.flush();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws NumberErrorException, IOException, TranscoderException {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2017, 6, 4);
        System.out.println(getEnd(calendar.getTime()));
        // StringBuilder result = new StringBuilder();
        // try {
        // BufferedReader br = new BufferedReader(new FileReader(new
        // File("E:\\ssText.txt")));// 构造一个BufferedReader类来读取文件
        // String s = null;
        // while ((s = br.readLine()) != null) {// 使用readLine方法，一次读一行
        // result.append(System.lineSeparator() + s);
        // }
        // br.close();
        // } catch (Exception e) {
        // e.printStackTrace();
        // }
        // System.out.println(result);
        // StringBuffer svgCode = new StringBuffer();
        // svgCode.append(
        // "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"473\"
        // height=\"190\" style=\"transform: translate(-235px, -75px);\"
        // viewBox=\"-235 -75 1258 399\"> <g><path stroke-linejoin=\"round\"
        // stroke-linecap=\"round\" stroke=\"#0033ff\" stroke-opacity=\"0.5\"
        // stroke-width=\"15\" fill=\"none\" class=\"leaflet-clickable\"
        // d=\"M404 107L470 174\"/></g> </svg>");
        //
        // convertToPng(result.toString(), "E:\\EEE.PNG");
        // InputStream inputStream =
        // ReportUtils.convertToPng(result.toString());
        // try {
        // FileOutputStream fos = new FileOutputStream(new File("E:\\DDD.PNG"));
        // byte[] read = new byte[1024];
        // int len = 0;
        // while ((len = inputStream.read(read)) != -1) {
        // fos.write(read, 0, len);
        // }
        // inputStream.close();
        // fos.flush();
        // fos.close();
        // } catch (Exception e1) {
        // e1.printStackTrace();
        // }

    }
}
